/// Iterator trait
/// 简单来说， for循环就是利用迭代器模式实现的一个语法糖 ，它属于外部迭代器。
/// 迭代器也是 Rust一致性的典型表现之一。不出所料， Rust中依然使用了 trait 来抽象迭代器模式。
pub fn start() {
    let counter1 = Counter::new(6);
    let mut counter2 = counter1.clone();

    println!("{:?}", counter1.size_hint());

    // for循环就是利用迭代器模式实现的一个语法糖
    for i in counter1 {
        println!("{}", i);
    }

    // 实际上是调用的next
    assert_eq!(Some(1), counter2.next());
    assert_eq!(Some(2), counter2.next());
    assert_eq!(Some(3), counter2.next());
    assert_eq!(Some(4), counter2.next());
    assert_eq!(Some(5), counter2.next());
    assert_eq!(Some(6), counter2.next());

    let a = [1, 2, 3];
    let mut iter = a.iter();
    assert_eq!((3, Some(3)), iter.size_hint());
    iter.next();
    assert_eq!((2, Some(2)), iter.size_hint());

    let iter = (0..10).filter(|x| x % 2 == 0);
    println!("{:?}", iter.size_hint());
    let iter = (0..10).filter(|x| x % 2 == 0).chain(15..20);
    println!("{:?}", iter.size_hint());

    let mut message = "Hello".to_string();
    message.extend(&[' ', 'R', 'u', 's', 't']);
    println!("{}", message)
}

#[derive(Clone)]
struct Counter {
    index: usize,
    count: usize,
}

impl Counter {
    const fn new(count: usize) -> Self {
        Self { count, index: 0 }
    }
}

impl Iterator for Counter {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.count {
            self.index += 1;
            Some(self.index)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let i = self.count - self.index;
        (i, Some(i))
    }
}

// 在 Iterator trait中还提供了一个方法叫 size_hint
// 源码：
//  fn size_hint(&self) -> (usize, Option<usize>) {
//      (0, None)
//  }
